from django.shortcuts import render
from rest_framework.views import APIView
from django.conf import settings
from urllib.parse import urlencode,parse_qs
from urllib.request import urlopen
from rest_framework.response import Response
from rest_framework import status
from .utils import QQOauthTool
from .models import OAuthQQUser

# Create your views here.

"""
urllib.parse.urlencode(query)
将query字典转换为url路径中的查询字符串

urllib.parse.parse_qs(qs)
将qs查询字符串格式数据转换为python的字典

urllib.request.urlopen(url, data=None)
发送http请求，如果data为None，发送GET请求，如果data不为None，发送POST请求
返回response响应对象，可以通过read()读取响应体数据，需要注意读取出的响应体数据为bytes类型
"""
# 1. 浏览器请求我们的服务器的时候需要生成一个url

# 2. 通过用户的扫描生成一个code


# 3. 通过code 换 token

# 4. 通过token换openid

# APIView
# GenericAPIView
#ListAPIView,CreateAPIView
class QQOauthURLView(APIView):

    """
    GET     /oauth/qq/statues/
    根据腾讯提交的接口文档,生成一个url

    """

    def get(self,request):

        """
        # 生成auth_url
        # https://graph.qq.com/oauth2.0/authorize
        # 请求参数请包含如下内容：
        # response_type   必须      授权类型，此值固定为“code”。
        # client_id       必须      申请QQ登录成功后，分配给应用的appid。
        # redirect_uri    必须      成功授权后的回调地址，必须是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
        # state           必须      client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
        # scope           可选      scope=get_user_info

        """

        # state = 'test'
        # # base_url 要添加问号
        # base_url = 'https://graph.qq.com/oauth2.0/authorize?'
        #
        # #组织一个字典,这个字典来存放参数
        # parmas = {
        #     'response_type':'code',
        #     'client_id':settings.QQ_APP_ID,
        #     'redirect_uri':settings.QQ_REDIRECT_URL,
        #     'state':state
        # }
        #
        # # 需要将字典的参数拼接到 base_url中
        # # urllib.parse.urlencode(query)
        # # 将query字典转换为url路径中的查询字符串
        #
        # auth_url = base_url + urlencode(parmas)
        # print(auth_url)

        qq = QQOauthTool()

        auth_url = qq.get_oauth_url()

        return Response({"auth_url":auth_url})

from rest_framework.generics import GenericAPIView
from .serializers import QQTokenSerializer
# 因为post中用到了序列化器,所以我们改变一下(不改也可以)
class QQTokenView(GenericAPIView):

    """
    GET /oauth/qq/?code=xxxxx
    我们通过获取的 code 来换取token

    """

    serializer_class = QQTokenSerializer

    def get(self,request):

        """
        # PC网站：https://graph.qq.com/oauth2.0/token
        # GET
        # grant_type      必须      授权类型，在本步骤中，此值为“authorization_code”。
        # client_id       必须      申请QQ登录成功后，分配给网站的appid。
        # client_secret   必须      申请QQ登录成功后，分配给网站的appkey。
        # code            必须      上一步返回的authorization
        # redirect_uri    必须      与上面一步中传入的redirect_uri保持一致。
        """

        code = request.query_params.get('code')

        if code is None:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # #注意添加 ?
        # base_url = 'https://graph.qq.com/oauth2.0/token?'
        #
        # params = {
        #     'grant_type':'authorization_code',
        #     'client_id':settings.QQ_APP_ID,
        #     'client_secret':settings.QQ_APP_KEY,
        #     'code':code,
        #     'redirect_uri':settings.QQ_REDIRECT_URL
        # }
        #
        #
        # url = base_url + urlencode(params)
        #
        #
        # # 我们自己去请求来获取数据
        # #通过urlopen来请求url中数据
        # response = urlopen(url)
        #
        # data = response.read().decode()
        # # parse_qs将获取的参数转换为字典
        # dict = parse_qs(data)
        #
        # access_tokens = dict.get('access_token')
        #
        # if access_tokens:
        #     access_token = access_tokens[0]

        #'access_token=C7299EDD52B07DC8B0B3DFF767909803&
        # expires_in=7776000&
        # refresh_token=CBCAC05971E8769268AC3DCFA5B72F6B'


        qq = QQOauthTool()

        access_token = qq.get_token_by_code(code)

        openid = qq.get_openid_by_token(access_token)

        if openid is None:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # openid 获取到了

        # 根据openid 来判断用户之前是否绑定过
        try:
            qquser = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 没有绑定过
            # 需要绑定
            token = OAuthQQUser.generic_token_by_openid(openid)

            return Response({"access_token":token})

        else:
            # else 什么执行,没有异常的时候
            #绑定过, 让它直接登录
            from rest_framework_jwt.settings import api_settings

            # 获取2个方法
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            # 调用这2个方法
            # 把用户的信息给 payload
            payload = jwt_payload_handler(qquser.user)
            token = jwt_encode_handler(payload)
            # user.token = token

            return Response({
                'token': token,
                'user_id': qquser.user.id,
                'username': qquser.user.username
            })




    def post(self,request):
        """
        1. 当用户点击保存的时候,需要把 access_token(openid),手机号,密码,短信验证码,post过来
        2.  access_token,短信验证码需要进行校验
        3. 需要将 user 和 openid保存入库

        """

        #.1.获取数据,然后校验
        # QQTokenSerializer(data=request.data)
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid()
        # 为什么返回user,因为我们要生成登录的token,所以在create方法中返回了user
        user = serializer.save()
        # 返回token
        # 需要在创建了用户之后,我们采用 jwt给它生成一个token
        from rest_framework_jwt.settings import api_settings

        # 获取2个方法
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        # 调用这2个方法
        # 把用户的信息给 payload
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        # user.token = token

        return Response({
            'token':token,
            'user_id':user.id,
            'username':user.username
        })







############itsdangerous#############
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

# 1. 创建序列化器对象
#secret_key,  秘钥
#  expires_in  有效期 秒数
serializer = Serializer('123',3600)

# 2. 对敏感数据进行编码
dict = {'openid':'123abc'}
token = serializer.dumps(dict)

#eyJpYXQiOjE1MzMwOTczNzYsImFsZyI6IkhTMjU2IiwiZXhwIjoxNTMzMTAwOTc2fQ.
# eyJvcGVuaWQiOiIxMjNhYmMifQ.
# AWMjwsf88sSfZqdzvEFMrUplp9tYWQeW48se41EcDXA'


serializer.loads(token)




serializer = Serializer('123',1)

#  对敏感数据进行编码
dict = {'openid':'123abc'}
token = serializer.dumps(dict)

#eyJpYXQiOjE1MzMwOTczNzYsImFsZyI6IkhTMjU2IiwiZXhwIjoxNTMzMTAwOTc2fQ.
# eyJvcGVuaWQiOiIxMjNhYmMifQ.
# AWMjwsf88sSfZqdzvEFMrUplp9tYWQeW48se41EcDXA'


serializer.loads(token)